package com.xxx.springboot.util;

import java.math.BigDecimal;
import java.text.DecimalFormat;

/**
 * 提供精确计算的double
 */
public class DoubleUtil {

    // 默认除法运算精度
    private static final int DEF_DIV_SCALE = 8;

    // 这个类不能实例化
    private DoubleUtil() {
    }

    /**
     * 提供精确的加法运算。
     * 
     * @param v1
     * @param v2
     * @return 两个参数的和
     */
    public static double add(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }

    /**
     * 提供精确的加法运算。
     * 
     * @param v1
     * @param v2
     * @param scale
     * @return 两个参数的和
     */
    public static double add(double v1, double v2, int scale) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    public static double addRoundDown(double v1, double v2, int scale) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).setScale(scale, BigDecimal.ROUND_DOWN).doubleValue();
    }

    /**
     * 提供精确的减法运算。
     * 
     * @param v1
     * @param v2
     * @return 两个参数的差
     */
    public static double subtract(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }

    /**
     * 提供精确的减法运算。
     * 
     * @param v1
     * @param v2
     * @param scale
     * @return 两个参数的差
     */
    public static double subtract(double v1, double v2, int scale) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 提供精确的乘法运算。
     * 
     * @param v1
     * @param v2
     * @return 两个参数的积
     */
    public static double multiply(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }

    /**
     * 提供精确的乘法运算。
     * 
     * @param v1
     * @param v2
     * @param scale
     * @return 两个参数的积
     */
    public static double multiply(double v1, double v2, int scale) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 提供（相对）精确的除法运算，当发生除不尽的情况时，精确到 小数点以后10位，以后的数字四舍五入。
     * 
     * @param v1
     * @param v2
     * @return 两个参数的商
     */
    public static double div(double v1, double v2) {
        return div(v1, v2, DEF_DIV_SCALE);
    }

    /**
     * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指 定精度，以后的数字四舍五入。
     * 
     * @param v1
     * @param v2
     * @param scale
     *            表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static double div(double v1, double v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 提供精确的小数位四舍五入处理。
     * 
     * @param v
     * @param scale
     * @return 四舍五入后的结果
     */
    public static double round(double v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * double转BigDecimal
     */
    public static BigDecimal double2BigDecimal(double d) {
        return new BigDecimal(String.valueOf(d));
    }

    public static String formatDouble8(double d) {
        DecimalFormat df = new DecimalFormat("#0.00000000");
        return df.format(d);
    }

    /**
     * 计算两个整数的百分比
     * @param num1
     * @param num2
     * @return
     */
    public static String calcPercent(int num1,int num2){
        String rate="0.00%";
        //定义格式化起始位数
        String format="0.00";
        if(num2 != 0 && num1 != 0){
            DecimalFormat dec = new DecimalFormat(format);
            rate =  dec.format((double) num1 / num2*100)+"%";
            while(true){
                if(rate.equals(format+"%")){
                    format=format+"0";
                    DecimalFormat dec1 = new DecimalFormat(format);
                    rate =  dec1.format((double) num1 / num2*100)+"%";
                }else {
                    break;
                }
            }
        }else if(num1 != 0 && num2 == 0){
            rate = "100%";
        }
        return rate;
    }

    /**
     * 把上面得到的百分比转为字符串类型的小数，保留两位小数
     * @author  shw
     */
    public static BigDecimal perToDecimal(String percent){
        String decimal = percent.substring(0,percent.indexOf("%"));
        BigDecimal bigDecimal = new BigDecimal(decimal);
        bigDecimal.divide(new BigDecimal("100"), 4, BigDecimal.ROUND_HALF_UP);
        return bigDecimal;
    }

    /**
     * main
     * 
     * @param args
     */
    public static void main(String[] args) {
//        String str = "1200.1000191243535222222221";
//        BigDecimal bigDec = new BigDecimal(str);
//        System.out.println("bigDec:" + bigDec);
//        System.out.println("doubleValue:" + bigDec.doubleValue());
//        System.out.println("bigDec.longValue():" + bigDec.longValue());
//        System.out.println("bigDec.intValue():" + bigDec.intValue());
//        double d = 100000.250121241;
//        System.out.println("d:" + d);
//        BigDecimal bigDecd = new BigDecimal(String.valueOf(d));
//        System.out.println("bigDecd:" + bigDecd);
//        System.out.println("bigDecd.doubleValue():" + bigDecd.doubleValue());
//        System.out.println(multiply(109233.122040, 0.034092, 10));
//        System.out.println(formatDouble8(multiply(109233.122040, 0.034092, 10)));
//        System.out.println(Double.valueOf(formatDouble8(multiply(109233.122040, 0.034092, 10))));

        System.out.println(calcPercent(12, 100));
        System.out.println(calcPercent(12, 50));
        System.out.println(calcPercent(12, 4));
        System.out.println(calcPercent(12, 33));
        System.out.println(perToDecimal(calcPercent(12, 33)));
    }
}
